<?php
namespace App\Services\Tool\Pay;
class AlipayTool{
    private $__gateway_new = 'https://mapi.alipay.com/gateway.do?';
    /**
     * 获取web支付链接
     */
    function getPayLink($input){
        $parameter = array(
            'service' => 'create_direct_pay_by_user',
            'partner' => env('alipay_pid'),
            'payment_type' => 1,
            'notify_url' => env('HOME_URL') . 'api/pay/alipay-notify',
            'return_url' => env('WEI_SHOP_URL') . 'cut-price/pay-already',
            'seller_email' => env('alipay_seller_id'),
            'out_trade_no' => $input['out_trade_no'],
            'subject' => $input['subject'],
            'total_fee' => $input['total_fee'],
            'body' => $input['body'],
            'it_b_pay' => null,
            'show_url' => null,
            'anti_phishing_key' => null,
            'exter_invoke_ip' => '112.74.133.153',
            '_input_charset' => strtolower('utf-8'),
            'qr_pay_mode' => 5
        );

        $para = $this->buildRequestPara($parameter);

        return $this->__gateway_new . $this->createLinkstringUrlencode($para);
    }

	/**
	 * 登陆授权
	 */
	function alipayAuth($input){
		$arr['apiname']    = 'com.alipay.account.auth';
        $arr['app_id']     = env('alipay_app_id');
        $arr['app_name']   = 'mc';
        $arr['auth_type']  = 'AUTHACCOUNT';
        $arr['biz_type']   = 'openservice';
        $arr['method']     = 'alipay.open.auth.sdk.code.get';
        $arr['pid']        = env('alipay_pid');
        $arr['product_id'] = 'WAP_FAST_LOGIN';
        $arr['scope']      = 'kuaijie';
        $arr['sign_type']  = 'RSA';
        $arr['target_id']  = $input['user_id'] . '';
        $data              = $this->getSignContent($arr);
        $arr['sign']       = $this->rsaSign($data,env('alipay_private_key'));
        $str = '';
        foreach($arr as $k=>$v){
            if($str != '') $str .= '&';
            $str .= $k . '=' . urlencode($v);
            $arr[$k] = urlencode($v);
        }
        return $str;
	}

	/**
	 * 换取授权访问令牌
	 */
	function alipayAuthToken($input){
		$arr['app_id']     = env('alipay_app_id');
		$arr['method']     = 'alipay.system.oauth.token';
		$arr['charset']    = 'utf-8';
		$arr['sign_type']  = 'RSA';
		$arr['timestamp']  = date('Y-m-d H:i:s',time());
		$arr['version']    = '1.0';
		$arr['grant_type'] = 'authorization_code';
		$arr['code']       = $input['code'];
		$data              = $this->getSignContent($arr);
        $arr['sign']       = $this->rsaSign($data,env('alipay_private_key'));
        $str = '';
        foreach($arr as $k=>$v){
            if($str != '') $str .= '&';
            $str .= $k . '=' . urlencode($v);
            $arr[$k] = urlencode($v);
        }

        $url        = 'https://openapi.alipay.com/gateway.do?' . $str;
        $ch         = curl_init ($url);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        $response   = curl_exec($ch);
        $response   = json_decode($response,true);dd($response['alipay_system_oauth_token_response']['access_token']);
        return $response['alipay_system_oauth_token_response']['access_token'];
	}

	/**
	 * 支付宝钱包用户信息共享kuaijieBd4bd4bc080764cef9d3a437433559A01
	 */
	function alipayUserInfo($input){
		$arr['app_id']     = env('alipay_app_id');
		$arr['method']     = 'alipay.user.get';
		$arr['charset']    = 'utf-8';
		$arr['sign_type']  = 'RSA';
		$arr['timestamp']  = date('Y-m-d H:i:s',time());
		$arr['version']    = '1.0';
		$arr['auth_token'] = $input['code'];
		$arr['fields']     = 'alipay_user_id,user_status,user_type,certified,real_name,logon_id,sex';
		$data              = $this->getSignContent($arr);
        $arr['sign']       = $this->rsaSign($data,env('alipay_private_key'));

        $str = '';
        foreach($arr as $k=>$v){
            if($str != '') $str .= '&';
            $str .= $k . '=' . urlencode($v);
            $arr[$k] = urlencode($v);
        }

        $url        = 'https://openapi.alipay.com/gateway.do?' . $str;
        $ch         = curl_init ($url);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        $response   = curl_exec($ch);
        dd($response);
        return $response;
	}

	/**
	 * 	登陆授权
	 */

	/**
	 * 获取返回时的签名验证结果
     * @param $para_temp 通知返回来的参数数组
     * @param $sign 返回的签名结果
     * @return 签名验证结果
    */
	function getSignVeryfy($para_temp, $sign,$config) {
		//除去待签名参数数组中的空值和签名参数
		$para_filter = $this->paraFilter($para_temp);
		//dd($para_temp);
		//对待签名参数数组排序
		$para_sort = $this->argSort($para_filter);

		//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
		$prestr = $this->createLinkstring($para_sort);
		//dd($para_filter,$para_sort,$prestr);

		$isSgin = false;
		switch (strtoupper(trim($para_temp['sign_type']))) {
			case "RSA" :
				$isSgin = $this->rsaVerify($prestr, env('alipay_public_key_verify'), $sign);

				break;
			case "MD5":
				$isSgin = $this->md5Verify($prestr,env('alipay_md5_key'),$sign);
				//var_dump('md5');
				break;
			default :
				$isSgin = false;
		}

		return $isSgin;
	}

    /**
     * 生成要请求给支付宝的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组
     */
    private function buildRequestPara($para_temp)
    {
        //除去待签名参数数组中的空值和签名参数
        $para_filter = $this->paraFilter($para_temp);

        //对待签名参数数组排序
        $para_sort = $this->argSort($para_filter);

        //生成签名结果
        $mysign = $this->buildRequestMd5sign($para_sort);

        //签名结果与签名方式加入请求提交参数组中
        $para_sort['sign'] = $mysign;
        $para_sort['sign_type'] = strtoupper(trim('md5'));

        return $para_sort;
    }

    /**
     * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串，并对字符串做urlencode编码
     * @param $para 需要拼接的数组
     * return 拼接完成以后的字符串
     */
    private function createLinkstringUrlencode($para)
    {
        $arg = '';
        while ((list ($key, $val) = each($para)) == true) {
            $arg .= $key . '=' . urlencode($val) . '&';
        }
        //去掉最后一个&字符
        $arg = substr($arg, 0, count($arg) - 2);

        //如果存在转义字符，那么去掉转义
        if (get_magic_quotes_gpc()) {
            $arg = stripslashes($arg);
        }

        return $arg;
    }

    /**
     * 生成签名结果
     * @param $para_sort 已排序要签名的数组
     * return 签名结果字符串
     */
    private function buildRequestMd5sign($para_sort)
    {
        //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = $this->createLinkstring($para_sort);

        $mysign = '';
        switch (strtoupper(trim('md5'))) {
            case 'MD5':
                $mysign = $this->md5Sign($prestr, env('alipay_md5_key'));
                break;
            default:
                $mysign = '';
        }

        return $mysign;
    }

    /**
     * 签名字符串
     * @param $prestr 需要签名的字符串
     * @param $key 私钥
     * return 签名结果
     */
    private function md5Sign($prestr, $key)
    {
        $prestr = $prestr . $key;
        return md5($prestr);
    }

	/**
	 * 除去数组中的空值和签名参数
	 * @param $para 签名参数组
	 * return 去掉空值与签名参数后的新签名参数组
	 */
	function paraFilter($para) {
		$para_filter = array();
		while (list ($key, $val) = each ($para)) {
			if($key == "sign" || $key == "sign_type" || $val == "")continue;
			else	$para_filter[$key] = $para[$key];
		}
		return $para_filter;
	}
	/**
	 * 对数组排序
	 * @param $para 排序前的数组
	 * return 排序后的数组
	 */
	function argSort($para) {
		ksort($para);
		reset($para);
		return $para;
	}
	/**
	 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * @param $para 需要拼接的数组
	 * return 拼接完成以后的字符串
	 */
	function createLinkstring($para) {
		$arg  = "";
		while (list ($key, $val) = each ($para)) {
			$arg.=$key."=".$val."&";
		}
		//去掉最后一个&字符
		$arg = substr($arg,0,count($arg)-2);

		//如果存在转义字符，那么去掉转义
		if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}

		return $arg;
	}
	/**
	 * RSA验签
	 * @param $data 待签名数据
	 * @param $alipay_public_key 支付宝的公钥字符串
	 * @param $sign 要校对的的签名结果
	 * return 验证结果
	 */
	function rsaVerify($data, $alipay_public_key, $sign)  {

		//以下为了初始化私钥，保证在您填写私钥时不管是带格式还是不带格式都可以通过验证。
		$alipay_public_key=str_replace("-----BEGIN PUBLIC KEY-----","",$alipay_public_key);
		$alipay_public_key=str_replace("-----END PUBLIC KEY-----","",$alipay_public_key);
		$alipay_public_key=str_replace("\n","",$alipay_public_key);
		$alipay_public_key='-----BEGIN PUBLIC KEY-----'.PHP_EOL.wordwrap($alipay_public_key, 64, "\n", true) .PHP_EOL.'-----END PUBLIC KEY-----';

		$res=openssl_get_publickey($alipay_public_key);
		//dd($data,base64_decode($sign));
		if($res)
		{
			$result = (bool)openssl_verify($data, base64_decode($sign), $res);
		}
		else {
			echo "您的支付宝公钥格式不正确!"."<br/>"."The format of your alipay_public_key is incorrect!";
			exit();
		}
		openssl_free_key($res);
		return $result;
	}
	/**
 	 * RSA签名
 	 * @param $data 待签名数据
 	 * @param $private_key 商户私钥字符串
 	 * return 签名结果
 	 */
	function rsaSign($data, $private_key) {
   		//以下为了初始化私钥，保证在您填写私钥时不管是带格式还是不带格式都可以通过验证。
   		$private_key=str_replace("-----BEGIN RSA PRIVATE KEY-----","",$private_key);
		$private_key=str_replace("-----END RSA PRIVATE KEY-----","",$private_key);
		$private_key=str_replace("\n","",$private_key);

		$private_key="-----BEGIN RSA PRIVATE KEY-----".PHP_EOL .wordwrap($private_key, 64, "\n", true). PHP_EOL."-----END RSA PRIVATE KEY-----";

   		$res=openssl_get_privatekey($private_key);

   		if($res)
   		{
   		    openssl_sign($data, $sign,$res);
   		}
   		else {
   		    echo "您的私钥格式不正确!"."<br/>"."The format of your private_key is incorrect!";
   		    return '';
   		}
   		openssl_free_key($res);
		//base64编码
   		$sign = base64_encode($sign);
   		return $sign;
	}
	/**
	 * md5验证签名
	 * @param $prestr 需要签名的字符串
	 * @param $sign 签名结果
	 * @param $key 私钥
	 * return 签名结果
	 */
	function md5Verify($prestr, $key, $sign) {
		$prestr = $prestr . $key;
		$mysgin = md5($prestr);
		//dd($mysgin,$sign);
		if($mysgin == $sign) {
			return true;
		} else {
			return false;
		}
	}

	function getSignContent($params) {
		ksort($params);

		$stringToBeSigned = "";
		$i = 0;
		foreach ($params as $k => $v) {
			if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {

				// 转换成目标字符集
				$v = $this->characet($v, 'UTF-8');

				if ($i == 0) {
					$stringToBeSigned .= "$k" . "=" . "$v";
				} else {
					$stringToBeSigned .= "&" . "$k" . "=" . "$v";
				}
				$i++;
			}
		}

		unset ($k, $v);
		return $stringToBeSigned;
	}

	/**
	 * 转换字符集编码
	 * @param $data
	 * @param $targetCharset
	 * @return string
	 */
	function characet($data, $targetCharset) {

		if (!empty($data)) {
			$fileType = 'UTF-8';
			if (strcasecmp($fileType, $targetCharset) != 0) {
				$data = mb_convert_encoding($data, $targetCharset, $fileType);
				//				$data = iconv($fileType, $targetCharset.'//IGNORE', $data);
			}
		}


		return $data;
	}
	/**
	 * 校验$value是否非空
	 *  if not set ,return true;
	 *    if is null , return true;
	 **/
	protected function checkEmpty($value) {
		if (!isset($value))
			return true;
		if ($value === null)
			return true;
		if (trim($value) === "")
			return true;

		return false;
	}
}
